import json
import requests

from django.http import JsonResponse
from django.shortcuts import render, HttpResponse
from django.forms import model_to_dict
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse

from web.forms.file import FileFolderModelForm, FileModelForm
from utils.tencent.cos import delete_file, delete_file_list, credential
from web import models


def file(request, project_id):
    """文件列表"""
    parent_obj = None
    folder_id = request.GET.get('folder', '')
    if folder_id.isdecimal():
        parent_obj = models.FileRepository.objects.filter(
            id=int(folder_id),
            file_type=2,
            project=request.tracer.project
        ).first()

    # GET 查看页面
    if request.method == "GET":
        # 导航条
        bread_crumb_list = []
        parent = parent_obj
        while parent:
            # bread_crumb_list.insert(0, {'id': parent.id, 'name':parent.name})
            bread_crumb_list.insert(0, model_to_dict(parent, ['id', 'name']))
            parent = parent.parent

        # 获取当前目录下所有的文件 & 文件夹
        form = FileFolderModelForm(request, parent_obj)
        queryset = models.FileRepository.objects.filter(
            project=request.tracer.project,
        )
        if parent_obj:
            # 进入了某个目录
            file_obj_list = queryset.filter(parent=parent_obj).order_by('-file_type')
        else:
            # 根目录
            file_obj_list = queryset.filter(parent__isnull=True).order_by('-file_type')
        context = {
            "form": form,
            'file_obj_list': file_obj_list,
            'bread_crumb_list': bread_crumb_list,
            'folder_obj': parent_obj
        }
        return render(request, 'file.html', context)

    # POST 添加文件夹 & 修改
    fid = request.POST.get('fid', '')
    edit_obj = None
    if fid.isdecimal():
        # 编辑操作
        edit_obj = models.FileRepository.objects.filter(id=int(fid), file_type=2,
                                                        project=request.tracer.project).first()
    if edit_obj:
        form = FileFolderModelForm(request, parent_obj, data=request.POST, instance=edit_obj)
    else:
        form = FileFolderModelForm(request, parent_obj, data=request.POST)

    if form.is_valid():
        form.instance.project = request.tracer.project
        form.instance.update_user = request.tracer.user
        form.instance.file_type = 2
        form.instance.parent = parent_obj

        form.save()
        return JsonResponse({'status': True})
    return JsonResponse({'status': False, 'error': form.errors})


def file_delete(request, project_id):
    """删除文件"""
    fid = request.GET.get('fid')

    # 级联删除(只删除了数据库中的值)
    del_obj = models.FileRepository.objects.filter(id=fid, project=request.tracer.project).first()
    if del_obj.file_type == 1:
        # 文件删除 (数据库文件删除, cos文件删除, 项目已使用空间容量归还)

        # 删除文件, 把容量还给当前项目的使用空间
        request.tracer.project.use_space -= del_obj.file_size
        request.tracer.project.save()

        # 去cos中删除文件
        delete_file(
            bucket=request.tracer.project.bucket,
            region=request.tracer.project.region,
            key=del_obj.key
        )
        # 在数据库中删除当前文件
        del_obj.delete()
        return JsonResponse({"status": True})

    # 文件夹删除 (找到文件夹下所有的文件 -> 数据库文件删除, cos文件删除, 项目已使用空间容量归还)

    total_size = 0
    key_list = []

    folder_list = [del_obj]
    for folder in folder_list:
        child = models.FileRepository.objects.filter(project=request.tracer.project, parent=folder).order_by(
            '-file_type')
        if child.file_type == 2:
            folder_list.append(child)
        else:
            # 文件大小
            total_size += child.file_size
            # 删除文件
            key_list.append({'Key': child.key})
    # cos批量删除文件
    if key_list:
        delete_file_list(
            bucket=request.tracer.project.bucket,
            region=request.tracer.project.region,
            key_list=key_list
        )
    # 归还容量
    if total_size:
        request.tracer.project.use_space -= total_size
        request.tracer.project.save()
    # 删除文件和文件夹(级联删除)
    del_obj.delete()
    return JsonResponse({"status": True})


@csrf_exempt
def cos_credential(request, project_id):
    """获取cos临时凭证"""
    # 容量限制: 单文件 & 总容量
    per_file_limit = request.tracer.price_policy.per_file_size * 1024 * 1024
    total_file_limit = request.tracer.price_policy.project_space * 1024 * 1024 * 1024
    total_size = 0
    # 获取每个文件&大小
    file_list = json.loads(request.body.decode('utf-8'))
    for item in file_list:
        # 上传的文件字节大小 item['size'] = B
        # 单文件限制的大小 MB
        # 超出限制
        if item['size'] > per_file_limit:
            msg = f"单文件超出限制 (最大: {request.tracer.price_policy.per_file_size} M, 文件: {item['name']})"
            return JsonResponse({"status": False, "error": msg})
        total_size += item['size']
    # 总容量进行限制

    if request.tracer.project.use_space + total_size > total_file_limit:
        return JsonResponse({"status": False, "error": '容量超过限制, 请升级套餐'})

    data_dict = credential(
        bucket=request.tracer.project.bucket,
        region=request.tracer.project.region
    )
    return JsonResponse({'status': True, 'data': data_dict})


@csrf_exempt
def file_post(request, project_id):
    """将已上传成功的文件写入数据库"""
    # 根据key再去cos获取文件Etag, 以校验合法性
    """
    name: fileName,
    key: key,
    file_size: fileSize,
    parent: CURRENT_FOLDER_ID,
    etag: data.ETag,
    file_path: data.Location
    """
    # 把获取到的数据添加到数据库
    form = FileModelForm(data=request.POST, request=request)
    if form.is_valid():
        # 校验通过, 写入数据库
        # form.instance.file_type = 1
        # form.instance.update_user = request.tracer.user
        # instance = form.save()
        data_dict = form.cleaned_data
        data_dict.pop('etag')
        data_dict.update({'project': request.tracer.project, 'file_type': 1, 'update_user': request.tracer.user})
        instance = models.FileRepository.objects.create(**data_dict)

        # 更新项目的已使用空间
        request.tracer.project.use_space += data_dict['file_size']
        request.tracer.project.save()

        result = {
            'id': instance.id,
            'name': instance.name,
            'file_size': instance.file_size,
            'username': instance.update_user.username,
            'datetime': instance.update_datetime.strftime('%Y年%m月%d日 %H:%M'),
            'download_url': reverse('file_download', kwargs={'project_id': project_id, 'file_id': instance.id})
            # 'file_type': instance.get_file_type_display()
        }
        return JsonResponse({"status": True, 'data': result})

    return JsonResponse({"status": False, 'data': '文件错误'})


def file_download(request, project_id, file_id):
    """下载文件"""
    # 获取文件内容 COS
    file_obj = models.FileRepository.objects.filter(id=file_id, project_id=project_id).first()
    res = requests.get(file_obj.file_path)
    data = res.content

    # 响应头
    response = HttpResponse(data)
    response['Content-Disposition'] = f"attachment; filename={file_obj.name}"
    return response


"""

"""